package cn.tedu.reflection;

import org.junit.jupiter.api.Test;

import javax.xml.ws.spi.Invoker;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


/*本类用于暴力反射*/
public class Testreflect{
    @Test
    /*暴力反射获取值与设置值*/
    public void test() throws Exception {
        //获取字节码文件对象
        Class<Person> personClass = Person.class;
        //获取指定名称私有属性
        Field name = personClass.getDeclaredField("name");
        //根据获取到的属性对象获取类型
        System.out.println(name.getType());//字节码对象
        System.out.println(name.getType().getName());//获取名字
        //设置属性的值
        //没有对象就通过反射设置对象
        Person person = personClass.newInstance();
        //设置私有可见
        name.setAccessible(true);
        name.set(person, "张三");
        System.out.println(person);


    }

    @Test
    /*通过暴力反射获取私有方法*/
    public void test1() throws Exception {
        Class<Person> personClass = Person.class;
        /*本方法的参数列表是(name,x,y,z...)
        * name:指的是要获取方法的名字
        * x,y,z...可变形参，指的是要获取方法的参数类型，注意是字节码对象*/
        Method method = personClass.getDeclaredMethod("add", String.class, int.class);
        method.setAccessible(true);
        //没有对象就通过反射获取对象
        Person person = personClass.newInstance();
        /*invoke()是用来调用目标方法，参数一是执行那个对象这个方法
        * 后续的参数是目标方法的形参*/
     method.invoke(person,"李四",18);
    }
    @Test
    public void test2(){
        Class []pers={Per.class};
        Object o = Proxy.newProxyInstance(Testreflect.class.getClassLoader(), pers, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("老色批之前");
                method.invoke(new Person());
                System.out.println("老色批之后");
                return null;
            }
        });
        Per per=(Per) o;

        per.lsp();
    }


}
